package com.opensource.afuluo.valve;

import com.google.common.base.Joiner;
import com.opensource.afuluo.ctx.Context;
import com.opensource.afuluo.enums.ProcessStatus;

/**
 * 原子操作流转阀门
 */
public interface Valve {

    default void prepare(Context ctx) {
        return;
    }

    default boolean accept(Context ctx) {
        return true;
    }

    default void background(Context ctx) {
        return;
    }

    void fire(Context ctx);

    default void lifecycle(Context ctx) {
        return;
    }

    default void post(Context ctx) {
        return;
    }

    default void finalize(Context ctx) {
        return;
    }

    default boolean isReact(Context ctx) {
        return ctx.isReact();
    }

    default void react(Context ctx) {
        ctx.markReact(true);
    }

    default void persistence(Context ctx) {
        return;
    }

    default void onException(Context ctx, Throwable t) {
        ctx.setStatus(ProcessStatus.FAILED, Joiner.on("@").join(
                ctx.getUnique(),
                this.getClass().getCanonicalName(),
                t.getMessage()
        ));
    }

    default void offer(Context ctx) {
        try {
            prepare(ctx);
            if (accept(ctx)) {
                if (!isReact(ctx)) {
                    fire(ctx);
                    lifecycle(ctx);
                    persistence(ctx);
                    post(ctx);
                } else {
                    react(ctx);
                }
            }
        } catch (Exception e) {
            onException(ctx, e);
        } finally {
            finalize(ctx);
        }
    }
}
